﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEngine;
using Utility;

namespace ViewController.LevelEditor
{
    public class LevelEditor : MonoBehaviour
    {
        /// <summary>
        ///     笔刷模式
        /// </summary>
        public enum BrushType
        {
            Ground,
            Hero
        }

        /// <summary>
        ///     操作模式
        /// </summary>
        public enum OperateMode
        {
            Draw,
            Erase
        }

        public SpriteRenderer emptyHighlight;

        private readonly Lazy<GUIStyle> _buttonStyle = new(() => new GUIStyle(GUI.skin.button)
        {
            fontSize = 30
        });

        private readonly Lazy<GUIStyle> _modeLabelStyle = new(() => new GUIStyle(GUI.skin.label)
        {
            fontSize = 30,
            alignment = TextAnchor.MiddleCenter
        });

        private readonly Lazy<GUIStyle> _rightButtonStyle = new(() => new GUIStyle(GUI.skin.button)
        {
            fontSize = 25
        });

        /// <summary>
        ///     是否可绘制
        /// </summary>
        private bool _canDraw;

        private BrushType _currentBrushType = BrushType.Ground;

        /// <summary>
        ///     当前鼠标下的 GameObject
        /// </summary>
        private GameObject _currentObjectMouseOn;

        private OperateMode _currentOperateMode = OperateMode.Draw;

        private void Update()
        {
            var mousePosition = Input.mousePosition;
            var worldMousePos = Camera.main!.ScreenToWorldPoint(mousePosition);

            worldMousePos.x = MathF.Floor(worldMousePos.x + 0.5f);
            worldMousePos.y = MathF.Floor(worldMousePos.y + 0.5f);
            worldMousePos.z = 0;

            if (GUIUtility.hotControl == 0)
                emptyHighlight.gameObject.SetActive(true);
            else
                emptyHighlight.gameObject.SetActive(false);

            // 与当前高亮块的 x y 值一样
            if (Math.Abs(emptyHighlight.transform.position.x - worldMousePos.x) < 0.1f &&
                Math.Abs(emptyHighlight.transform.position.y - worldMousePos.y) < 0.1f)
            {
                // 不做任何事情
            }
            else
            {
                // 设置高亮块的位置
                var emptyHighlightPos = worldMousePos;
                emptyHighlightPos.z = -1;
                emptyHighlight.transform.position = emptyHighlightPos;

                // 发出射线
                var ray = Camera.main!.ScreenPointToRay(mousePosition);
                var hit = Physics2D.Raycast(ray.origin, Vector2.zero, Mathf.Infinity);

                // 有碰撞说明是有地块
                if (hit.collider)
                {
                    if (_currentOperateMode == OperateMode.Draw)
                        // 红色代表不能绘制
                        emptyHighlight.color = new Color(1, 0, 0, 0.5f);
                    else
                        // 橙色代表可擦除
                        emptyHighlight.color = new Color(1, 0.5f, 0, 0.5f);

                    _canDraw = false;
                    _currentObjectMouseOn = hit.collider.gameObject;
                }
                else
                {
                    if (_currentOperateMode == OperateMode.Draw)
                        // 白色代表可以绘制
                        emptyHighlight.color = new Color(1, 1, 1, 0.5f);
                    else
                        // 蓝色代表橡皮状态
                        emptyHighlight.color = new Color(0, 0, 1, 0.5f);

                    _canDraw = true;
                    _currentObjectMouseOn = null;
                }
            }

            if ((Input.GetMouseButtonDown(0) || Input.GetMouseButton(0)) && GUIUtility.hotControl == 0)
            {
                // 增加是否可以绘制的判断
                if (_canDraw && _currentOperateMode == OperateMode.Draw)
                {
                    if (_currentBrushType == BrushType.Ground)
                    {
                        var groundPrefab = Resources.Load<GameObject>("Ground");
                        var groundGameObj = Instantiate(groundPrefab, transform);

                        groundGameObj.transform.position = worldMousePos;
                        groundGameObj.name = "Ground";
                    }
                    else if (_currentBrushType == BrushType.Hero)
                    {
                        var groundPrefab = Resources.Load<GameObject>("Ground");
                        var groundGameObj = Instantiate(groundPrefab, transform);

                        groundGameObj.transform.position = worldMousePos;
                        groundGameObj.name = "Player";

                        // 用青色代替主角
                        groundGameObj.GetComponent<SpriteRenderer>().color = Color.cyan;
                    }

                    // 红色代表不能绘制
                    emptyHighlight.color = new Color(1, 0, 0, 0.5f);

                    _canDraw = false;
                }
                else if (_currentObjectMouseOn && _currentOperateMode == OperateMode.Erase)
                {
                    Destroy(_currentObjectMouseOn);

                    // 蓝色代表橡皮状态
                    emptyHighlight.color = new Color(0, 0, 1, 0.5f);

                    _currentObjectMouseOn = null;
                }
            }
        }

        private void OnGUI()
        {
            var modeLabelRect = RectHelper.RectForAnchorCenter(Screen.width * 0.5f, 35, 200, 50);

            // 显示当前模式
            if (_currentOperateMode == OperateMode.Draw)
                GUI.Label(modeLabelRect, _currentOperateMode + ":" + _currentBrushType, _modeLabelStyle.Value);
            else
                GUI.Label(modeLabelRect, _currentOperateMode.ToString(), _modeLabelStyle.Value);

            var drawButtonRect = new Rect(10, 10, 150, 40);
            if (GUI.Button(drawButtonRect, "绘制", _buttonStyle.Value)) _currentOperateMode = OperateMode.Draw;

            var eraseButtonRect = new Rect(10, 60, 150, 40);
            if (GUI.Button(eraseButtonRect, "橡皮", _buttonStyle.Value)) _currentOperateMode = OperateMode.Erase;

            if (_currentOperateMode == OperateMode.Draw)
            {
                var groundButtonRect = new Rect(Screen.width - 110, 10, 100, 40);
                if (GUI.Button(groundButtonRect, "地块", _rightButtonStyle.Value)) _currentBrushType = BrushType.Ground;

                var heroButtonRect = new Rect(Screen.width - 110, 60, 100, 40);
                if (GUI.Button(heroButtonRect, "主角", _rightButtonStyle.Value)) _currentBrushType = BrushType.Hero;
            }

            var saveButtonRect = new Rect(Screen.width - 110, Screen.height - 50, 100, 40);
            if (GUI.Button(saveButtonRect, "保存", _rightButtonStyle.Value))
            {
                var infos = new List<LevelItemInfo>(transform.childCount);

                // 搜集
                foreach (Transform child in transform)
                {
                    var childPos = child.position;

                    infos.Add(new LevelItemInfo
                    {
                        X = childPos.x,
                        Y = childPos.y,
                        Name = child.name
                    });
                }

                var document = new XmlDocument();

                var declaration = document.CreateXmlDeclaration("1.0", "UTF-8", "");
                document.AppendChild(declaration);

                // 根节点
                var level = document.CreateElement("Level");
                document.AppendChild(level);

                foreach (var levelItemInfo in infos)
                {
                    var levelItem = document.CreateElement("LevelItem");

                    levelItem.SetAttribute("name", levelItemInfo.Name);
                    levelItem.SetAttribute("x", levelItemInfo.X + "");
                    levelItem.SetAttribute("y", levelItemInfo.Y + "");

                    level.AppendChild(levelItem);
                }

                // var stringBuilder = new StringBuilder();
                // var stringWriter = new StringWriter(stringBuilder);
                // var xmlWriter = new XmlTextWriter(stringWriter);
                // xmlWriter.Formatting = Formatting.Indented;
                // document.WriteTo(xmlWriter);
                // Debug.Log(stringBuilder.ToString());

                var levelFilesFolder = Application.persistentDataPath + "/LevelFiles";
                Debug.Log(levelFilesFolder);

                if (!Directory.Exists(levelFilesFolder)) Directory.CreateDirectory(levelFilesFolder);

                var levelFilePath = levelFilesFolder + "/" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xml";

                // 将 xml 写入到文件路径
                document.Save(levelFilePath);
            }
        }

        private class LevelItemInfo
        {
            public string Name;
            public float X;
            public float Y;
        }
    }
}